package cn.tedu.baking;

import org.junit.jupiter.api.Test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * java反射机制
 * 反射这个技术,可以在运行期间来动态决定创建对象,调用对象的某个方法,获取对象的属性等内容.
 * 之前的代码,都是在编译期间 书写要执行的内容.
 * 而反射允许我们在运行期间 决定到底要创建哪个类对象,或哪个对象的方法.
 *  xxx.java ---> xxx.class 字节码文件  运行时 JVM 加载 运行 .class字节码文件
 */
public class ReflectDemo {
    @Test
    void reflectTest() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        // HelloClass .class 字节码文件  包含了 HelloClass.java文件的所有信息
        // new HelloClass() ---> HelloClass.class加载方法区
        // new HelloClass() ---> 创建Class类对象
        Class stringClass = String.class; //类名.class 可以获取类的信息
        System.out.println(stringClass.getName());
        Class aClass = new String().getClass();// 通过对象 可以获取类的class的信息
        System.out.println(aClass.getSimpleName());//可以直接获取类名
        Class aClass1 = Class.forName("java.lang.String");//可以通过给定类的全包名获取
        System.out.println(aClass1.getSimpleName());
        Method[] methods = aClass1.getMethods();//通过字节码对象信息获取该类中所有公开方法
        for (Method method : methods) {
            //System.out.println(method);
        }
        Method[] declaredMethods = aClass1.getDeclaredMethods();//获取公开+ 私有的所有方法
        for (Method method : declaredMethods) {
            //System.out.println(method);
        }
        //getMethod(方法名,获取的方法有参数则写参数类型.class)
        Method compareTo = aClass1.getMethod("compareTo", String.class);
        System.out.println(compareTo);
        Class<?> p1 = Class.forName("cn.tedu.baking.Person");
        Object o = p1.newInstance();//通过字节码信息 创建对象
        if(o instanceof  Person){ //判断o变量中的对象 是不是Person类型

            Method sayHi = p1.getMethod("sayHi",int.class);//通过字节码信息获取sayHi方法
            sayHi.invoke(o,100); //通过invoke 方法执行sayHi方法,需要传递执行对象
        }
    }

}
